package com.franklin.java.service.database.ui;

import com.franklin.java.api.ui.MessageActionListener;
import com.franklin.java.api.ui.jpanel.AbstractComponent;
import com.franklin.java.api.ui.jpanel.button.MyButton;
import com.franklin.java.entity.CostTime;
import com.franklin.java.entity.sql.JdbcInfo;
import com.franklin.java.service.database.JdbcService;
import com.franklin.java.service.database.JdbcState;
import com.franklin.java.utils.DocumentUtils;
import com.franklin.java.utils.EditorUtils;
import com.franklin.java.utils.SwingUtils;
import com.franklin.plugins.common.utils.DataCheckUtils;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.project.Project;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * Sql Console的元素
 * @author Franklin
 * @since 2021/9/25 17:13
 */
public class SqlConsoleForm extends AbstractComponent {
    /**
     * 主面板
     */
    private JPanel mainPanel;
    private MyButton runSqlButton;
    /**
     * 详情面板
     */
    private JPanel detailPanel;
    private JPanel sqlPanel;
    private MyButton removeSqlButton;
    private JLabel timeLabel;

    private final Project project;
    private final String sql;
    private Editor editor;
    private BiConsumer<ResultSet,CostTime> resultSetConsumer;
    private final JdbcResultForm jdbcResultForm;
    private boolean isRemove = false;

    public SqlConsoleForm(Project project, String sql, BiConsumer<ResultSet,CostTime> resultSetConsumer, JdbcResultForm jdbcResultForm) {
        this.project = project;
        this.sql = sql;
        this.resultSetConsumer = resultSetConsumer;
        this.jdbcResultForm = jdbcResultForm;
        this.timeLabel.setText(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")));
        init();
    }

    @Override
    public JPanel getMainPanel() {
        return mainPanel;
    }

    private void init() {
        iniSqlPanel();
        initRunSqlButton();
    }

    MyButton getRemoveSqlButton() {
        return removeSqlButton;
    }

    String getTime(){
        return this.timeLabel.getText();
    }

    void remove(){
        this.isRemove = true;
    }

    boolean isRemove(){
        return this.isRemove;
    }

    JPanel getDetailPanel() {
        return detailPanel;
    }

    private void initRunSqlButton() {
        this.runSqlButton.addActionListener(
            new MessageActionListener<CostTime>(
                "",
                true, this.detailPanel,this.jdbcResultForm.getDetailPanel()
            ) {
                @Override
                protected CostTime handleActionEvent(ActionEvent e) throws Exception {
                    JdbcService jdbcService = JdbcService.getInstance();
                    JdbcInfo lastJdbcInfo = JdbcState.getLastJdbcInfo();
                    if (Objects.isNull(lastJdbcInfo)){
                        return CostTime.ZERO;
                    }
                    String sql = SqlConsoleForm.this.sql;
                    String editorSql = SqlConsoleForm.this.editor.getDocument().getText();
                    if (DataCheckUtils.isNotEmpty(editorSql)){
                        sql = editorSql;
                    }
                    try {
                        return jdbcService.executeQuery(lastJdbcInfo, sql + jdbcResultForm.getLimit(), resultSetConsumer);
                    } catch (SQLException exception) {

                    }
                    throw new RuntimeException("Sql execution failed");
                }
            }
        );
    }

    private void iniSqlPanel() {
        EditorFactory editorFactory = EditorFactory.getInstance();
        Document document = editorFactory.createDocument("");
        this.editor = editorFactory.createEditor(document);
        EditorUtils.initEditor(this.editor);

        this.sqlPanel.removeAll();
        this.sqlPanel.setLayout(SwingUtils.createLayoutManager(1, 1));
        JComponent editorComponent = this.editor.getComponent();

        this.addCell(this.sqlPanel,editorComponent,0,0,new Dimension(500,600));

        refreshSqlPanel(sql);
    }

    private void refreshSqlPanel(CharSequence content){
        ((EditorImpl) editor).setViewer(false);
        DocumentUtils.writeSync(project, () -> editor.getDocument().setText(content));
        ((EditorEx) editor)
            .setHighlighter(EditorHighlighterFactory.getInstance()
                .createEditorHighlighter(project,  UUID.randomUUID() +"mybatis.sql")
            );
    }
}
